<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>给你曾经心动的感觉</title>
    <style>
      code[class*='language-'],
      pre[class*='language-'] {
        color: #155e63;
        background: none;
        font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
        text-align: left;
        white-space: pre;
        word-spacing: normal;
        word-break: normal;
        word-wrap: normal;
        line-height: 1.5;

        -moz-tab-size: 4;
        -o-tab-size: 4;
        tab-size: 4;

        -webkit-hyphens: none;
        -moz-hyphens: none;
        -ms-hyphens: none;
        hyphens: none;
      }

      /* Code blocks */
      pre[class*='language-'] {
        padding: 1em;
        margin: 0.5em 0;
        overflow: auto;
      }

      :not(pre) > code[class*='language-'],
      pre[class*='language-'] {
        background: none;
      }

      /* Inline code */
      :not(pre) > code[class*='language-'] {
        padding: 0.1em;
        border-radius: 0.3em;
        white-space: normal;
      }

      .token.comment,
      .token.block-comment,
      .token.prolog,
      .token.doctype,
      .token.cdata {
        color: not specified;
      }

      .token.punctuation {
        color: not specified;
      }

      .token.tag,
      .token.attr-name,
      .token.namespace,
      .token.deleted {
        color: #e2777a;
      }

      .token.function-name {
        color: #6196cc;
      }

      .token.boolean,
      .token.number,
      .token.function {
        color: #f08d49;
      }

      .token.property,
      .token.class-name,
      .token.constant,
      .token.symbol {
        color: not specified;
      }

      .token.selector,
      .token.important,
      .token.atrule,
      .token.keyword,
      .token.builtin {
        color: not specified;
      }

      .token.string,
      .token.char,
      .token.attr-value,
      .token.regex,
      .token.variable {
        color: #7ec699;
      }

      .token.operator,
      .token.entity,
      .token.url {
        color: #67cdcc;
      }

      .token.important,
      .token.bold {
        font-weight: bold;
      }
      .token.italic {
        font-style: italic;
      }

      .token.entity {
        cursor: help;
      }

      .token.inserted {
        color: green;
      }
    </style>
    <style id="styleTag"></style>
  </head>
  <body>
    <pre id="content" class="language-css"></pre>

    <script>
      var content = document.getElementById('content');
      var strStyle = document.getElementById('styleTag');
      var n = 0;
      var speed = 10;
      // var strOne = "\/*大家好，我叫曾鸣鸿，曾小贤的曾，鸣人的鸣，黄飞鸿的鸿。*\/\n\/*闲来无事，css 喷吐效果给摸出了点苗头*\/\n\/*刚开始是各种头疼，解决完之后，发现并没有那么困难。*\/\n\/*哈哈哈哈哈哈哈。。。[仰天长笑.gif]*\/\n\/*先加个背景色，白色太耀眼。*\/\nbody {\n  transition: all 1.5s;\n  background: #EEE;\n}\n#content {\n  width: 100%;\n  height: 70%;\n}\n\/*给写 css 的纸张加个背景色啊，纸张大小啥的，再加个圆角。*\/\n#content {\n  transition: all 1.5s;\n  position: absolute;\n  background: #2d2d2d;\n  border-radius: 0.3em;\n  width: 45%;\n  height: 92%;\n  padding: 10px;\n  box-shadow: 8px 8px 5px #30e3ca;\n}\n\/*这个背景色跟字体颜色那么接近，字都快看不到了，给注释改个颜色。*\/\n.token.comment {\n  color: #999;\n}\n\/*再给 css 左边的关键字换个颜色。*\/\n.token.property {\n  color: #f8c555;\n}\n\/*给选择器换个颜色。*\/\n.token.selector {\n  color: #cc99cd;\n}\n\/*给标点符号和括号加个白色。*\/\n.token.punctuation {\n  color: #ccc;\n}\n\/*滚动条隐藏一下。*\/\n#content::-webkit-scrollbar {\n  display:none;\n}\n\/*将代码块先放到右边。*\/\n#content {\n  position: absolute;\n  right: 10px;\n}\n";
      var strOne =
        '\/*水印：不爱喝汽水*\/\n\/*先加个背景色，白色太耀眼。*\/\nbody {\n  transition: all 1.5s;\n  background: #EEE;\n}\n#content {\n  width: 100%;\n  height: 70%;\n}\n\/*给写 css 的纸张加个背景色啊，纸张大小啥的，再加个圆角。*\/\n#content {\n  transition: all 1.5s;\n  position: absolute;\n  background: #2d2d2d;\n  border-radius: 0.3em;\n  width: 45%;\n  height: 92%;\n  padding: 10px;\n  box-shadow: 8px 8px 5px #30e3ca;\n}\n\/*这个背景色跟字体颜色那么接近，字都快看不到了，给注释改个颜色。*\/\n.token.comment {\n  color: #999;\n}\n\/*再给 css 左边的关键字换个颜色。*\/\n.token.property {\n  color: #f8c555;\n}\n\/*给选择器换个颜色。*\/\n.token.selector {\n  color: #cc99cd;\n}\n\/*给标点符号和括号加个白色。*\/\n.token.punctuation {\n  color: #ccc;\n}\n\/*滚动条隐藏一下。*\/\n#content::-webkit-scrollbar {\n  display:none;\n}\n\/*将代码块先放到右边。*\/\n#content {\n  position: absolute;\n  right: 10px;\n}\n';

      var strTwo =
        "\/*在左边画个桃心。*\/\n#content-two {\n  position: relative;\n  left: 16%;\n  top: 15rem;  \n  -webkit-animation: heartbeat 1s infinite;\n  width: 200px;\n  height: 200px;\n  background: #f00;\n  filter: drop-shadow(0px 0px 20px rgb(255,20,20));\n  transform: rotate(45deg);\n}\n#content-two:before, #content-two:after {\n  content: '';\n  position: absolute;\n  width: 200px;\n  height: 200px;\n  background: #f00;\n  border-radius: 100px;\n}\n#content-two:before {\n  left: -100px;\n}\n#content-two:after {\n  left: 0;\n  top: -100px;\n}\n";

      var strThree =
        // '\/*给你们一点心动的感觉。*\/\n@keyframes heartbeat {\n  0% {\n    transform:rotate(45deg) scale(0.8,0.8);\n    opacity:1;\n  }\n  25% {\n    transform:rotate(45deg) scale(1,1);\n    opacity:0.8;\n  }\n  100% {\n    transform:rotate(45deg) scale(0.8,0.8);\n    opacity:1;\n  }\n}\n\/*说难不难，就是排版比较麻烦。*\/\n\/*Show Time 到此结束，撒花 ~ 撒花 ~ 。*\/\n';
        '\/*给你们一点心动的感觉。*\/\n@keyframes heartbeat {\n  0% {\n    transform:rotate(45deg) scale(0.8,0.8);\n    opacity:1;\n  }\n  25% {\n    transform:rotate(45deg) scale(1,1);\n    opacity:0.8;\n  }\n  100% {\n    transform:rotate(45deg) scale(0.8,0.8);\n    opacity:1;\n  }\n}\n\/*Show Time 到此结束，撒花 ~ 撒花 ~ 。*\/\n';

      var sumStr = strOne + strTwo + strThree;

      var controller = setInterval(put, speed);

      function put() {
        n++;
        // console.log(sumStr);
        if (n > 0) {
          content.innerHTML = sumStr.substring(0, n);
          strStyle.innerHTML = sumStr.substring(0, n);
          content.innerHTML = Prism.highlight(
            sumStr.substring(0, n),
            Prism.languages.css
          );
        }

        if (n > 400) {
          content.scrollTop = content.scrollHeight;
        }

        if (n > strOne.length) {
          if (document.getElementById('content-two')) {
            console.log(n);
          } else {
            var contentTwo = document.createElement('pre');
            contentTwo.id = 'content-two';
            document.body.appendChild(contentTwo);
          }
        }

        if (n > sumStr.length) {
          window.clearInterval(controller);
        }
      }
    </script>
    <script>
      var _self =
        typeof window !== 'undefined'
          ? window // if in browser
          : typeof WorkerGlobalScope !== 'undefined' &&
            self instanceof WorkerGlobalScope
          ? self // if in worker
          : {}; // if in node js

      var Prism = (function () {
        // Private helper vars
        var lang = /\blang(?:uage)?-([\w-]+)\b/i;
        var uniqueId = 0;

        var _ = (_self.Prism = {
          manual: _self.Prism && _self.Prism.manual,
          disableWorkerMessageHandler:
            _self.Prism && _self.Prism.disableWorkerMessageHandler,
          util: {
            encode: function (tokens) {
              if (tokens instanceof Token) {
                return new Token(
                  tokens.type,
                  _.util.encode(tokens.content),
                  tokens.alias
                );
              } else if (_.util.type(tokens) === 'Array') {
                return tokens.map(_.util.encode);
              } else {
                return tokens
                  .replace(/&/g, '&amp;')
                  .replace(/</g, '&lt;')
                  .replace(/\u00a0/g, ' ');
              }
            },

            type: function (o) {
              return Object.prototype.toString
                .call(o)
                .match(/\[object (\w+)\]/)[1];
            },

            objId: function (obj) {
              if (!obj['__id']) {
                Object.defineProperty(obj, '__id', { value: ++uniqueId });
              }
              return obj['__id'];
            },

            // Deep clone a language definition (e.g. to extend it)
            clone: function (o, visited) {
              var type = _.util.type(o);
              visited = visited || {};

              switch (type) {
                case 'Object':
                  if (visited[_.util.objId(o)]) {
                    return visited[_.util.objId(o)];
                  }
                  var clone = {};
                  visited[_.util.objId(o)] = clone;

                  for (var key in o) {
                    if (o.hasOwnProperty(key)) {
                      clone[key] = _.util.clone(o[key], visited);
                    }
                  }

                  return clone;

                case 'Array':
                  if (visited[_.util.objId(o)]) {
                    return visited[_.util.objId(o)];
                  }
                  var clone = [];
                  visited[_.util.objId(o)] = clone;

                  o.forEach(function (v, i) {
                    clone[i] = _.util.clone(v, visited);
                  });

                  return clone;
              }

              return o;
            },
          },

          languages: {
            extend: function (id, redef) {
              var lang = _.util.clone(_.languages[id]);

              for (var key in redef) {
                lang[key] = redef[key];
              }

              return lang;
            },

            /**
             * Insert a token before another token in a language literal
             * As this needs to recreate the object (we cannot actually insert before keys in object literals),
             * we cannot just provide an object, we need anobject and a key.
             * @param inside The key (or language id) of the parent
             * @param before The key to insert before. If not provided, the function appends instead.
             * @param insert Object with the key/value pairs to insert
             * @param root The object that contains `inside`. If equal to Prism.languages, it can be omitted.
             */
            insertBefore: function (inside, before, insert, root) {
              root = root || _.languages;
              var grammar = root[inside];

              if (arguments.length == 2) {
                insert = arguments[1];

                for (var newToken in insert) {
                  if (insert.hasOwnProperty(newToken)) {
                    grammar[newToken] = insert[newToken];
                  }
                }

                return grammar;
              }

              var ret = {};

              for (var token in grammar) {
                if (grammar.hasOwnProperty(token)) {
                  if (token == before) {
                    for (var newToken in insert) {
                      if (insert.hasOwnProperty(newToken)) {
                        ret[newToken] = insert[newToken];
                      }
                    }
                  }

                  ret[token] = grammar[token];
                }
              }

              // Update references in other language definitions
              _.languages.DFS(_.languages, function (key, value) {
                if (value === root[inside] && key != inside) {
                  this[key] = ret;
                }
              });

              return (root[inside] = ret);
            },

            // Traverse a language definition with Depth First Search
            DFS: function (o, callback, type, visited) {
              visited = visited || {};
              for (var i in o) {
                if (o.hasOwnProperty(i)) {
                  callback.call(o, i, o[i], type || i);

                  if (
                    _.util.type(o[i]) === 'Object' &&
                    !visited[_.util.objId(o[i])]
                  ) {
                    visited[_.util.objId(o[i])] = true;
                    _.languages.DFS(o[i], callback, null, visited);
                  } else if (
                    _.util.type(o[i]) === 'Array' &&
                    !visited[_.util.objId(o[i])]
                  ) {
                    visited[_.util.objId(o[i])] = true;
                    _.languages.DFS(o[i], callback, i, visited);
                  }
                }
              }
            },
          },
          plugins: {},

          highlightAll: function (async, callback) {
            _.highlightAllUnder(document, async, callback);
          },

          highlightAllUnder: function (container, async, callback) {
            var env = {
              callback: callback,
              selector:
                'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code',
            };

            _.hooks.run('before-highlightall', env);

            var elements =
              env.elements || container.querySelectorAll(env.selector);

            for (var i = 0, element; (element = elements[i++]); ) {
              _.highlightElement(element, async === true, env.callback);
            }
          },

          highlightElement: function (element, async, callback) {
            // Find language
            var language,
              grammar,
              parent = element;

            while (parent && !lang.test(parent.className)) {
              parent = parent.parentNode;
            }

            if (parent) {
              language = (parent.className.match(lang) || [
                ,
                '',
              ])[1].toLowerCase();
              grammar = _.languages[language];
            }

            // Set language on the element, if not present
            element.className =
              element.className.replace(lang, '').replace(/\s+/g, ' ') +
              ' language-' +
              language;

            if (element.parentNode) {
              // Set language on the parent, for styling
              parent = element.parentNode;

              if (/pre/i.test(parent.nodeName)) {
                parent.className =
                  parent.className.replace(lang, '').replace(/\s+/g, ' ') +
                  ' language-' +
                  language;
              }
            }

            var code = element.textContent;

            var env = {
              element: element,
              language: language,
              grammar: grammar,
              code: code,
            };

            _.hooks.run('before-sanity-check', env);

            if (!env.code || !env.grammar) {
              if (env.code) {
                _.hooks.run('before-highlight', env);
                env.element.textContent = env.code;
                _.hooks.run('after-highlight', env);
              }
              _.hooks.run('complete', env);
              return;
            }

            _.hooks.run('before-highlight', env);

            if (async && _self.Worker) {
              var worker = new Worker(_.filename);

              worker.onmessage = function (evt) {
                env.highlightedCode = evt.data;

                _.hooks.run('before-insert', env);

                env.element.innerHTML = env.highlightedCode;

                callback && callback.call(env.element);
                _.hooks.run('after-highlight', env);
                _.hooks.run('complete', env);
              };

              worker.postMessage(
                JSON.stringify({
                  language: env.language,
                  code: env.code,
                  immediateClose: true,
                })
              );
            } else {
              env.highlightedCode = _.highlight(
                env.code,
                env.grammar,
                env.language
              );

              _.hooks.run('before-insert', env);

              env.element.innerHTML = env.highlightedCode;

              callback && callback.call(element);

              _.hooks.run('after-highlight', env);
              _.hooks.run('complete', env);
            }
          },

          highlight: function (text, grammar, language) {
            var env = {
              code: text,
              grammar: grammar,
              language: language,
            };
            _.hooks.run('before-tokenize', env);
            env.tokens = _.tokenize(env.code, env.grammar);
            _.hooks.run('after-tokenize', env);
            return Token.stringify(_.util.encode(env.tokens), env.language);
          },

          matchGrammar: function (
            text,
            strarr,
            grammar,
            index,
            startPos,
            oneshot,
            target
          ) {
            var Token = _.Token;

            for (var token in grammar) {
              if (!grammar.hasOwnProperty(token) || !grammar[token]) {
                continue;
              }

              if (token == target) {
                return;
              }

              var patterns = grammar[token];
              patterns =
                _.util.type(patterns) === 'Array' ? patterns : [patterns];

              for (var j = 0; j < patterns.length; ++j) {
                var pattern = patterns[j],
                  inside = pattern.inside,
                  lookbehind = !!pattern.lookbehind,
                  greedy = !!pattern.greedy,
                  lookbehindLength = 0,
                  alias = pattern.alias;

                if (greedy && !pattern.pattern.global) {
                  // Without the global flag, lastIndex won't work
                  var flags = pattern.pattern.toString().match(/[imuy]*$/)[0];
                  pattern.pattern = RegExp(pattern.pattern.source, flags + 'g');
                }

                pattern = pattern.pattern || pattern;

                // Don’t cache length as it changes during the loop
                for (
                  var i = index, pos = startPos;
                  i < strarr.length;
                  pos += strarr[i].length, ++i
                ) {
                  var str = strarr[i];

                  if (strarr.length > text.length) {
                    // Something went terribly wrong, ABORT, ABORT!
                    return;
                  }

                  if (str instanceof Token) {
                    continue;
                  }

                  if (greedy && i != strarr.length - 1) {
                    pattern.lastIndex = pos;
                    var match = pattern.exec(text);
                    if (!match) {
                      break;
                    }

                    var from = match.index + (lookbehind ? match[1].length : 0),
                      to = match.index + match[0].length,
                      k = i,
                      p = pos;

                    for (
                      var len = strarr.length;
                      k < len &&
                      (p < to || (!strarr[k].type && !strarr[k - 1].greedy));
                      ++k
                    ) {
                      p += strarr[k].length;
                      // Move the index i to the element in strarr that is closest to from
                      if (from >= p) {
                        ++i;
                        pos = p;
                      }
                    }

                    // If strarr[i] is a Token, then the match starts inside another Token, which is invalid
                    if (strarr[i] instanceof Token) {
                      continue;
                    }

                    // Number of tokens to delete and replace with the new match
                    delNum = k - i;
                    str = text.slice(pos, p);
                    match.index -= pos;
                  } else {
                    pattern.lastIndex = 0;

                    var match = pattern.exec(str),
                      delNum = 1;
                  }

                  if (!match) {
                    if (oneshot) {
                      break;
                    }

                    continue;
                  }

                  if (lookbehind) {
                    lookbehindLength = match[1] ? match[1].length : 0;
                  }

                  var from = match.index + lookbehindLength,
                    match = match[0].slice(lookbehindLength),
                    to = from + match.length,
                    before = str.slice(0, from),
                    after = str.slice(to);

                  var args = [i, delNum];

                  if (before) {
                    ++i;
                    pos += before.length;
                    args.push(before);
                  }

                  var wrapped = new Token(
                    token,
                    inside ? _.tokenize(match, inside) : match,
                    alias,
                    match,
                    greedy
                  );

                  args.push(wrapped);

                  if (after) {
                    args.push(after);
                  }

                  Array.prototype.splice.apply(strarr, args);

                  if (delNum != 1)
                    _.matchGrammar(text, strarr, grammar, i, pos, true, token);

                  if (oneshot) break;
                }
              }
            }
          },

          tokenize: function (text, grammar, language) {
            var strarr = [text];

            var rest = grammar.rest;

            if (rest) {
              for (var token in rest) {
                grammar[token] = rest[token];
              }

              delete grammar.rest;
            }

            _.matchGrammar(text, strarr, grammar, 0, 0, false);

            return strarr;
          },

          hooks: {
            all: {},

            add: function (name, callback) {
              var hooks = _.hooks.all;

              hooks[name] = hooks[name] || [];

              hooks[name].push(callback);
            },

            run: function (name, env) {
              var callbacks = _.hooks.all[name];

              if (!callbacks || !callbacks.length) {
                return;
              }

              for (var i = 0, callback; (callback = callbacks[i++]); ) {
                callback(env);
              }
            },
          },
        });

        var Token = (_.Token = function (
          type,
          content,
          alias,
          matchedStr,
          greedy
        ) {
          this.type = type;
          this.content = content;
          this.alias = alias;
          // Copy of the full string this token was created from
          this.length = (matchedStr || '').length | 0;
          this.greedy = !!greedy;
        });

        Token.stringify = function (o, language, parent) {
          if (typeof o == 'string') {
            return o;
          }

          if (_.util.type(o) === 'Array') {
            return o
              .map(function (element) {
                return Token.stringify(element, language, o);
              })
              .join('');
          }

          var env = {
            type: o.type,
            content: Token.stringify(o.content, language, parent),
            tag: 'span',
            classes: ['token', o.type],
            attributes: {},
            language: language,
            parent: parent,
          };

          if (o.alias) {
            var aliases =
              _.util.type(o.alias) === 'Array' ? o.alias : [o.alias];
            Array.prototype.push.apply(env.classes, aliases);
          }

          _.hooks.run('wrap', env);

          var attributes = Object.keys(env.attributes)
            .map(function (name) {
              return (
                name +
                '="' +
                (env.attributes[name] || '').replace(/"/g, '&quot;') +
                '"'
              );
            })
            .join(' ');

          return (
            '<' +
            env.tag +
            ' class="' +
            env.classes.join(' ') +
            '"' +
            (attributes ? ' ' + attributes : '') +
            '>' +
            env.content +
            '</' +
            env.tag +
            '>'
          );
        };

        if (!_self.document) {
          if (!_self.addEventListener) {
            // in Node.js
            return _self.Prism;
          }

          if (!_.disableWorkerMessageHandler) {
            // In worker
            _self.addEventListener(
              'message',
              function (evt) {
                var message = JSON.parse(evt.data),
                  lang = message.language,
                  code = message.code,
                  immediateClose = message.immediateClose;

                _self.postMessage(_.highlight(code, _.languages[lang], lang));
                if (immediateClose) {
                  _self.close();
                }
              },
              false
            );
          }

          return _self.Prism;
        }

        //Get current script and highlight
        var script =
          document.currentScript ||
          [].slice.call(document.getElementsByTagName('script')).pop();

        if (script) {
          _.filename = script.src;

          if (!_.manual && !script.hasAttribute('data-manual')) {
            if (document.readyState !== 'loading') {
              if (window.requestAnimationFrame) {
                window.requestAnimationFrame(_.highlightAll);
              } else {
                window.setTimeout(_.highlightAll, 16);
              }
            } else {
              document.addEventListener('DOMContentLoaded', _.highlightAll);
            }
          }
        }

        return _self.Prism;
      })();

      if (typeof module !== 'undefined' && module.exports) {
        module.exports = Prism;
      }

      // hack for components to work correctly in node.js
      if (typeof global !== 'undefined') {
        global.Prism = Prism;
      }
      Prism.languages.css = {
        comment: /\/\*[\s\S]*?\*\//,
        atrule: {
          pattern: /@[\w-]+?.*?(?:;|(?=\s*\{))/i,
          inside: {
            rule: /@[\w-]+/,
            // See rest below
          },
        },
        url: /url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,
        selector: /[^{}\s][^{};]*?(?=\s*\{)/,
        string: {
          pattern: /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
          greedy: true,
        },
        property: /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,
        important: /\B!important\b/i,
        function: /[-a-z0-9]+(?=\()/i,
        punctuation: /[(){};:]/,
      };

      Prism.languages.css['atrule'].inside.rest = Prism.languages.css;

      if (Prism.languages.markup) {
        Prism.languages.insertBefore('markup', 'tag', {
          style: {
            pattern: /(<style[\s\S]*?>)[\s\S]*?(?=<\/style>)/i,
            lookbehind: true,
            inside: Prism.languages.css,
            alias: 'language-css',
            greedy: true,
          },
        });

        Prism.languages.insertBefore(
          'inside',
          'attr-value',
          {
            'style-attr': {
              pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,
              inside: {
                'attr-name': {
                  pattern: /^\s*style/i,
                  inside: Prism.languages.markup.tag.inside,
                },
                punctuation: /^\s*=\s*['"]|['"]\s*$/,
                'attr-value': {
                  pattern: /.+/i,
                  inside: Prism.languages.css,
                },
              },
              alias: 'language-css',
            },
          },
          Prism.languages.markup.tag
        );
      }
    </script>
  </body>
</html>
